package key.w8.boot.reference;


import key.w8.boot.annotation.K8ReferenceService;
import key.w8.boot.contenxt.ReferenceContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;

/**
 * @Author: k8
 * @CreateTime: 2025-08-17
 * @Version: 1.0
 */
/**
 * 处理@K8Reference注解的后置处理器
 * 负责扫描注解字段、注册FactoryBean并完成注入
 */
public class K8ReferenceBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;
    private DefaultListableBeanFactory beanFactory;
    private ReferenceBuilder referenceBuilder;
    /**
     * 获取Spring上下文和Bean工厂
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        // 获取Spring的默认Bean工厂（用于动态注册Bean）
        this.beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        referenceBuilder = beanFactory.getBean(ReferenceBuilder.class);
    }

    /**
     * Bean初始化前执行的逻辑：扫描并处理@K8Reference注解字段
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 遍历当前Bean的所有字段
        ReflectionUtils.doWithFields(bean.getClass(), field -> {
            // 检查字段是否标注了@K8Reference注解
            K8ReferenceService k8Reference = AnnotationUtils.getAnnotation(field, K8ReferenceService.class);
            if (k8Reference != null) {
                // 处理带有注解的字段
                processAnnotatedField(bean, field, k8Reference);
            }
        });
        return bean;
    }

    /**
     * 处理带有@K8Reference注解的字段
     */
    private void processAnnotatedField(Object targetBean, Field field, K8ReferenceService annotation) {
        // 1. 校验字段类型必须是接口
        Class<?> fieldType = field.getType();
        if (!fieldType.isInterface()) {
            throw new IllegalArgumentException(
                    "字段 " + field.getName() + " 标注了@K8Reference，但类型不是接口（" + fieldType.getName() + "）"
            );
        }
        ReferenceContext referenceContext = new ReferenceContext();
        referenceContext.setVersion(annotation.version());
        referenceContext.setType((Class<Object>) fieldType);
        referenceContext.setGroup(annotation.group());
        referenceContext.setProtocol(annotation.protocol());
        Object value = referenceBuilder.build(referenceContext);
        injectFieldValue(targetBean, field, value);
    }


    /**
     * 从FactoryBean获取实例并注入到目标字段
     */
    private void injectFieldValue(Object targetBean, Field field, Object value) {
        try {
            // 注入到目标字段（设置字段可访问，突破private限制）
            field.setAccessible(true);
            field.set(targetBean, value);
        } catch (Exception e) {
            throw new RuntimeException(
                    "注入@K8Reference字段失败，字段名：" + field.getName() + "，接口：" + field.getType().getName(),
                    e
            );
        }
    }

    /**
     * Bean初始化后执行的逻辑（此处无需处理）
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

